package org.yuanqiframework.yuanqi.core.utils;

import java.lang.reflect.Field;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class MapEntityUtils {

    // 缓存字段信息提升性能
    private static final Map<Class<?>, Map<String, Field>> FIELD_CACHE = new ConcurrentHashMap<>();
    // 日期格式缓存
    private static final Map<Class<?>, SimpleDateFormat> DATE_FORMAT_CACHE = new ConcurrentHashMap<>();

    /**
     * 将 Map 转换为实体对象 (增强版)
     * @param map 包含字段数据的 Map
     * @param clazz 目标实体类
     * @return 转换后的实体对象
     * @throws RuntimeException 如果转换失败
     */
    public static <T> T mapToEntity(Map<String, Object> map, Class<T> clazz) {
        if (map == null || map.isEmpty()) {
            return null;
        }

        try {
            T entity = clazz.getDeclaredConstructor().newInstance();
            Map<String, Field> fieldMap = getClassFields(clazz);

            for (Map.Entry<String, Object> entry : map.entrySet()) {
                String mapKey = entry.getKey();
                Object value = entry.getValue();

                // 下划线转驼峰
                String fieldName = toCamelCase(mapKey);
                Field field = fieldMap.get(fieldName);

                if (field != null && value != null) {
                    field.setAccessible(true);
                    field.set(entity, convertValue(field.getType(), value));
                }
            }
            return entity;
        } catch (Exception e) {
            throw new RuntimeException("Map转换实体失败", e);
        }
    }

    // 获取类的所有字段(带缓存)
    private static Map<String, Field> getClassFields(Class<?> clazz) {
        return FIELD_CACHE.computeIfAbsent(clazz, k -> {
            Map<String, Field> fieldMap = new HashMap<>();
            for (Field field : clazz.getDeclaredFields()) {
                fieldMap.put(field.getName(), field);
            }
            return fieldMap;
        });
    }

    // 类型转换器
    private static Object convertValue(Class<?> targetType, Object value) {
        if (value == null) return null;

        // 类型相同直接返回
        if (targetType.isAssignableFrom(value.getClass())) {
            return value;
        }

        try {
            // String -> Date 转换
            if (targetType == Date.class && value instanceof String) {
                SimpleDateFormat sdf = DATE_FORMAT_CACHE.computeIfAbsent(
                        targetType,
                        k -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
                );
                return sdf.parse(value.toString());
            }
            // 其他基本类型转换
            if (targetType == Integer.class || targetType == int.class) {
                return Integer.parseInt(value.toString());
            }
            if (targetType == Long.class || targetType == long.class) {
                return Long.parseLong(value.toString());
            }
            if (targetType == Double.class || targetType == double.class) {
                return Double.parseDouble(value.toString());
            }
            if (targetType == Boolean.class || targetType == boolean.class) {
                return Boolean.parseBoolean(value.toString());
            }
        } catch (ParseException e) {
            throw new RuntimeException("日期格式转换失败: " + value, e);
        } catch (NumberFormatException e) {
            throw new RuntimeException("数字格式转换失败: " + value, e);
        }

        return value;
    }

    // 下划线转驼峰
    private static String toCamelCase(String name) {
        if (name == null || !name.contains("_")) {
            return name;
        }

        StringBuilder result = new StringBuilder();
        String[] parts = name.split("_");
        result.append(parts[0].toLowerCase());

        for (int i = 1; i < parts.length; i++) {
            if (!parts[i].isEmpty()) {
                result.append(parts[i].substring(0, 1).toUpperCase())
                        .append(parts[i].substring(1).toLowerCase());
            }
        }
        return result.toString();
    }

    // 原 mapListToEntityList 方法保持不变
    public static <T> List<T> mapListToEntityList(List<Map<String, Object>> mapList, Class<T> clazz) {
        List<T> entityList = new ArrayList<>();
        if (mapList == null || mapList.isEmpty()) {
            return entityList;
        }

        for (Map<String, Object> map : mapList) {
            entityList.add(mapToEntity(map, clazz));
        }
        return entityList;
    }
}
